﻿using System;
using System.Collections.Generic;
using Microsoft.Practices.Unity;
using JTLeigh.Commerce.Spencer.Core.Common;
using JTLeigh.Commerce.Spencer.Features.ProductImages.Business.Services;

// aliases for entities
using LocalizedProductImageE = JTLeigh.Commerce.Spencer.Features.ProductImages.Common.Entities.LocalizedProductImage;
using LocalizedProductImageViewE = JTLeigh.Commerce.Spencer.Features.ProductImages.Common.Entities.LocalizedProductImageView;
using LocalizedProductImageSizeE = JTLeigh.Commerce.Spencer.Features.ProductImages.Common.Entities.LocalizedProductImageSize;
using ProductImageVariantE = JTLeigh.Commerce.Spencer.Features.ProductImages.Common.Entities.ProductImageVariant;

// aliases for contracts
using GetProductImagesRequestC = JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Contracts.Runtime.GetProductImages.GetProductImagesRequest;
using GetProductImagesResponseC = JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Contracts.Runtime.GetProductImages.GetProductImagesResponse;
using ProductImageC = JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Contracts.Runtime.GetProductImages.ProductImage;
using ProductImageViewC = JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Contracts.Runtime.GetProductImages.ProductImageView;
using ProductImageSizeC = JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Contracts.Runtime.GetProductImages.ProductImageSize;
using ProductImageVariantC = JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Contracts.Runtime.GetProductImages.ProductImageVariant;

namespace JTLeigh.Commerce.Spencer.Features.ProductImages.Service.Commands.Runtime
{

	/// <summary>
	/// Command for getting all images for a single product, including all views and sizes.
	/// </summary>
	public class GetProductImagesCommand
	{

		#region Properties

		/// <summary>
		/// Gets or sets the product image metadata service to use to get product image metadata.
		/// </summary>
		/// <value>An <see cref="IProductImageMetadataService"/> implementation.</value>
		[Dependency]
		public IProductImageMetadataService ProductImageMetadataService { get; set; }

		/// <summary>
		/// Gets or sets the product image service to use to get product images.
		/// </summary>
		/// <value>An <see cref="IProductImageService"/> implementation.</value>
		[Dependency]
		public IProductImageService ProductImageService { get; set; }

		#endregion // Properties

		#region Methods

		/// <summary>
		/// Gets all images for a single product, including all views and sizes.
		/// </summary>
		/// <param name="request">The <see cref="GetProductImagesRequestC"/> request object.</param>
		/// <returns>The <see cref="GetProductImagesResponseC"/> response object.</returns>
		public GetProductImagesResponseC GetProductImages(GetProductImagesRequestC request)
		{
			Dictionary<Guid, LocalizedProductImageE> images;
			Dictionary<Guid, LocalizedProductImageViewE> views;
			Dictionary<Guid, LocalizedProductImageSizeE> sizes;
			LocalizedProductImageViewE view;
			LocalizedProductImageSizeE size;
			GetProductImagesResponseC response;
			ProductImageC imageC;

			Safety.AssertArgumentNotNull("request", request);

			images = ProductImageService.GetProductImages(request.TenantId, request.ProductId.CatalogId, request.ProductId.ProductId, request.CultureId);
			views = new Dictionary<Guid, LocalizedProductImageViewE>();
			sizes = new Dictionary<Guid, LocalizedProductImageSizeE>();
			foreach (LocalizedProductImageE image in images.Values)
			{
				if (!views.ContainsKey(image.ViewId))
				{
					view = ProductImageMetadataService.GetProductImageViewByViewId(request.TenantId, image.ViewId, request.CultureId);
					if (view != null)
					{
						views.Add(view.ViewId, view);
					}
				}
				foreach (ProductImageVariantE variant in image.Variants.Values)
				{
					if (!sizes.ContainsKey(variant.SizeId))
					{
						size = ProductImageMetadataService.GetProductImageSizeBySizeId(request.TenantId, variant.SizeId, request.CultureId);
						if (size != null)
						{
							sizes.Add(size.SizeId, size);
						}
					}
				}
			}

			response = new GetProductImagesResponseC
			{
				Images = new Dictionary<Guid, ProductImageC>(),
				Views = new Dictionary<Guid, ProductImageViewC>(),
				Sizes = new Dictionary<Guid, ProductImageSizeC>()
			};
			foreach (LocalizedProductImageE image in images.Values)
			{
				imageC = new ProductImageC
				{
					AlternativeText = image.AlternativeText,
					UsagePermissionText = image.UsagePermissionText,
					ViewId = image.ViewId,
					Variants = new Dictionary<Guid, ProductImageVariantC>()
				};
				response.Images.Add(image.ImageId, imageC);
				foreach (ProductImageVariantE variant in image.Variants.Values)
				{
					imageC.Variants.Add(variant.SizeId, new ProductImageVariantC
					{
						SizeId = variant.SizeId,
						Path = variant.Path
					});
				}
			}
			foreach (LocalizedProductImageViewE viewO in views.Values)
			{
				response.Views.Add(viewO.ViewId, new ProductImageViewC
				{
					ViewId = viewO.ViewId,
					WellKnownViewCode = viewO.WellKnownViewCode,
					DisplayOrder = viewO.DisplayOrder,
					Name = viewO.Name
				});
			}
			foreach (LocalizedProductImageSizeE sizeO in sizes.Values)
			{
				response.Sizes.Add(sizeO.SizeId, new ProductImageSizeC
				{
					SizeId = sizeO.SizeId,
					WellKnownSizeCode = sizeO.WellKnownSizeCode,
					Width = sizeO.Width,
					Height = sizeO.Height,
					DisplayOrder = sizeO.DisplayOrder,
					Name = sizeO.Name
				});
			}

			return response;
		}

		#endregion // Methods

	}

}
